package com.example.demo.utils;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.bind.annotation.RequestBody;

import java.io.IOException;
import java.net.SocketTimeoutException;
import java.util.HashMap;
import java.util.Map;

/**
 * @Author: jiangzhuang
 * @Email: jiangzhuang@primeton.com
 * @Date: 2020/7/21
 * @Desc: OKHttp Utils(Based on OKHttp 3.10.0)
 */
public class OKHttpUtils {

    private static Logger logger = LoggerFactory.getLogger(OKHttpUtils.class);

    private static OkHttpClient client = new OkHttpClient();

    /**
     * Get Query
     *
     * @param url
     * @param params
     * @param auth     authentication info, auth[0]: username, auth[1]: password
     * @return results
     */
    public static String Get(String url, Map<String,Object> params, String[] auth) throws IOException {
        // OKHttp Basic Auth
        final String credential = Credentials.basic(auth[0],auth[1]);
        // OKHttp Request
        Request request = new Request.Builder()
                .header("Authorization",credential)
                .url(getParams(url,params)).build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

            logger.info("OKHttp Get Url: "+ url +" Request Successfully! Code:"+response.code());
            return response.body() != null ? response.body().string() : null;
        }
        catch (SocketTimeoutException e){
            logger.error("OKHttp Post Request Timeout, Check Your Network Connective Please!");
            throw e;
        }
    }

    /**
     * Post Query
     *
     * @param url
     * @param params
     * @return
     */
    public static String Post(String url, Map<String,String> params, String[] auth) throws IOException {
        // OKHttp Basic Auth
        final String credential = Credentials.basic(auth[0],auth[1]);
        // OKHttp Request
        Request request = new Request.Builder()
                .header("Authorization",credential).url(url)
                .post(postFormParams(params)).build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()) throw new IOException("Unexpected code " + response);

            logger.info("OKHttp Post Url: "+ url + " Request Successfully! Code: "+ response.body());
            return response.body() != null ? response.body().string() : null;
        }
        catch (SocketTimeoutException e){
            logger.error("OKHttp Post Request Timeout, Check Your Network Connective Please!");
            throw e;
        }
    }

    /**
     * Post Query
     *
     * @param url
     * @param jsonStr
     * @return
     */
    public static String Post(String url, String jsonStr, String[] auth) throws IOException {
        // OKHttp Basic Auth
        final String credential = Credentials.basic(auth[0],auth[1]);
        // OKHttp Request
        Request request = new Request.Builder()
                .header("Authorization",credential).url(url)
                .post(postJsonParams(jsonStr)).build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()){
                logger.error("OKHttp Post Request Failed! Params:\t"+jsonStr);
                throw new IOException("Unexpected code " + response);
            }

            logger.info("OKHttp Post Url: "+ url +" Request Successfully! Code: "+response.code());
            return response.body() != null ? response.body().string() : null;
        }
        catch (SocketTimeoutException e){
            logger.error("OKHttp Post Request Timeout, Check Your Network Connective Please!");
            throw e;
        }
    }

    /**
     * Delete Query
     *
     * @param url
     * @param auth      authentication info, auth[0]: username, auth[1]: password
     * @return
     */
    public static String Delete(String url, String[] auth) throws IOException {
        // OKHttp Basic Auth
        final String credentials = Credentials.basic(auth[0], auth[1]);
        // OKHttp Request
        Request request = new Request.Builder().header("Authorization",credentials)
                .url(url).delete().build();

        try (Response response = client.newCall(request).execute()) {
            if (!response.isSuccessful()){
                logger.error("OKHttp Delete Request Failed! url:\t"+url);
                throw new IOException("Unexpected code " + response);
            }

            logger.info("OKHttp Delete Url: "+ url +" Request Successfully! Code:\t"+response.code());
            return response.body() != null ? response.body().string() : null;
        }
        catch (SocketTimeoutException e){
            logger.error("OKHttp Delete Request Timeout, Check Your Network Connective Please!");
            throw e;
        }
    }

    // --------------------------------------- Utils Private Method

    /**
     * Generate Get Urls From Map
     *
     * @param url       request url
     * @param params    request params
     * @return results
     */
    private static String getParams(String url, Map<String,Object> params){
        StringBuilder urlBuilder = new StringBuilder(url);

        if(params != null && !params.isEmpty()){
            urlBuilder.append("?").append(Joiner.on('&').withKeyValueSeparator('=').join(params));
        }

        return urlBuilder.toString();
    }

    /**
     * Generate Post Request Form Body From Map
     *
     * @param params
     * @return results
     */
    private static RequestBody postFormParams(Map<String,String> params){
        FormBody.Builder formBodyBuilder = new FormBody.Builder();

        if(!params.isEmpty()){
            params.forEach(formBodyBuilder::add);
        }

        return formBodyBuilder.build();
    }

    /**
     * Generate Post Request Json Body From Map
     *
     * @param jsonStr
     * @return results
     */
    private static RequestBody postJsonParams(String jsonStr){
        // POST Body Type
        MediaType JSON = MediaType.parse("application/json; charset=utf-8");

        return RequestBody.create(JSON,jsonStr);
    }


    // --------------------------------------- Utils Test Method
    @Test
    public void GetUtilTest() throws IOException {
        String url = "http:192.168.1.171/api/projects";
        String[] auth = new String[]{"admin","Harbor12345"};
        Map<String,Object> map = new HashMap<>();

        /*map.put("name","library");*/

        String result = OKHttpUtils.Get(url, map, auth);

        System.out.println(result);
    }

    @Test
    public void PostJSONUtilTest() throws IOException {
        String url = "http:192.168.1.171/api/projects";
        String[] auth = new String[]{"admin","Harbor12345"};

        HarborProjectVo hpv = new HarborProjectVo();
        hpv.setProject_name("xxxxx");

        String result = OKHttpUtils.Post(url, JSON.toJSONString(hpv), auth);

        System.out.println(result);
    }

    @Test
    public void DeleteUtilTest() throws IOException {
        String url = "http:192.168.1.171/api/projects/39";
        String[] auth = new String[]{"admin","Harbor12345"};

        String response = OKHttpUtils.Delete(url, auth);

        logger.info(response);
    }
}